import 'dart:io';

import 'package:camera/camera.dart';
import 'package:fish_redux/fish_redux.dart';
import 'package:flutter/cupertino.dart' hide Action;
import 'package:flutter/material.dart' hide Action;
import 'package:multi_image_picker/multi_image_picker.dart';
import 'package:path/path.dart' as Path;
import 'package:path_provider/path_provider.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:www.znpigai.teacher/global_store/state.dart';
import 'package:www.znpigai.teacher/utils/http.dart';
import 'package:www.znpigai.teacher/utils/nav.dart';
import 'package:www.znpigai.teacher/utils/progress_dialog.dart';
import 'package:www.znpigai.teacher/utils/util.dart';

import 'action.dart';
import 'state.dart';

Effect<AnswerEditState> buildEffect() {
  return combineEffects(<Object, Effect<AnswerEditState>>{
    Lifecycle.initState: _onInit,
    AnswerEditAction.onTakePhoto: _onTakePhoto,
    AnswerEditAction.onAiSubmit: _onAiSubmit,
    AnswerEditAction.onVoiceAi: _onVoiceAi,
    AnswerEditAction.onSubmit: _onSubmit,
    AnswerEditAction.onDemand: _onDemand,
  });
}

void _onInit(Action action, Context<AnswerEditState> ctx) async {
  Future.delayed(Duration.zero, () async {
    var cameras = await availableCameras();
    var controller = CameraController(cameras[0], ResolutionPreset.medium);
    await controller.initialize();
    ctx.dispatch(AnswerEditActionCreator.initCamera(cameras[0], controller));

    // 销毁时自动保存
    ctx.onDisposed(() {
      String title = ctx.state.titleEditController.text;
      String content = ctx.state.contentEditController.text;
      var url = '/correct/${GlobalState.userRole}/api/homework/save.mvc';
      Http.post(url, data: {
        'id': ctx.state.answer.id,
        'title': title,
        'content': content,
        'finish': '1'
      });
    });

    // get token
    var pr = new ProgressDialog(ctx.context)..setMessage('请等待...');
    pr.show();
    HttpResult result =
        await Http.get("/correct/pub/api/third/aliyun/voice/gettoken.mvc");
    pr.hide();

    if (result.success) {
      ctx.dispatch(AnswerEditActionCreator.token(result.data['token']));
    } else {
      Util.alertFail(result, ctx.context);
    }

    // 请求权限
    const permissionGroups = [
      PermissionGroup.microphone,
    ];

    Map<PermissionGroup, PermissionStatus> permissions =
        await PermissionHandler().requestPermissions(permissionGroups);

    var denies = [];
    permissions.forEach((key, value) {
      if (value == PermissionStatus.denied) {
        denies.add(key);
      }
    });

    if (denies.isNotEmpty) {
      var msg = denies.join("\n");
      Util.showMsgDialog("权限", "$msg\n没有麦克风权限将无法进行语音录入", ctx.context);
    }
  });
}

void _onTakePhoto(Action action, Context<AnswerEditState> ctx) async {
  try {
    var resultList = await MultiImagePicker.pickImages(
        maxImages: 300,
        enableCamera: true,
        cupertinoOptions: CupertinoOptions(takePhotoIcon: "chat"),
        materialOptions: MaterialOptions(
          actionBarColor: "#abcdef",
          actionBarTitle: "选择照片",
          allViewTitle: "All Photos",
          selectCircleStrokeColor: "#000000",
        ));

    if (resultList.length > 0) {
      ctx.state.photos = resultList;
      if (ctx.state.photos != null) {
        for (int i = 0; i < ctx.state.photos.length; i++) {
          ctx.dispatch(AnswerEditActionCreator.doingOcr(i));
          var photo = ctx.state.photos[i];
          var photoData = await photo.requestOriginal(quality: 80);
          HttpResult result = await Http.uploadPhoto(
              "/publicUploadAction_upload",
              photoBuffer: photoData.buffer.asUint8List());
          if (result.success) {
            var ocr = {
              'title': result.data['articleTitle'].toString(),
              'content': result.data['articleWithoutTitle'].toString()
            };
            ctx.dispatch(AnswerEditActionCreator.doneOcr(ocr));
          } else {
            ctx.dispatch(AnswerEditActionCreator.doneOcr({}));
            Util.alertFail(result, ctx.context);
          }
        }
      }
    } else {
      Util.alert('请选择照片', ctx.context);
    }
  } catch (e) {
    print(e);
  }
}

void _onTakePhotoOld(Action action, Context<AnswerEditState> ctx) async {
  String select = await Util.showBottomSelectDialog(
      '小IN目前只支持手写体哟！', {'camera': '拍照', 'gallery': '相册'}, ctx.context);
  if (select == 'camera') {
    final path = Path.join(
      // Store the picture in the temp directory.
      // Find the temp directory using the `path_provider` plugin.
      (await getTemporaryDirectory()).path,
      '${DateTime.now()}.png',
    );

    // Attempt to take a picture and log where it's been saved.
    await ctx.state.controller.takePicture(path);

    ctx.dispatch(AnswerEditActionCreator.doingOcr(1));
    var photoData = await File(path).readAsBytes();
    HttpResult result = await Http.uploadPhoto("/publicUploadAction_upload",
        photoBuffer: photoData);
    if (result.success) {
      var ocr = {
        'title': result.data['articleTitle'].toString(),
        'content': result.data['articleWithoutTitle'].toString()
      };
      ctx.dispatch(AnswerEditActionCreator.doneOcr(ocr));
    } else {
      ctx.dispatch(AnswerEditActionCreator.doneOcr({}));
      Util.alertFail(result, ctx.context);
    }
  } else {
    // 相册
    try {
      var resultList = await MultiImagePicker.pickImages(
          maxImages: 300,
          enableCamera: true,
          cupertinoOptions: CupertinoOptions(takePhotoIcon: "chat"),
          materialOptions: MaterialOptions(
            actionBarColor: "#abcdef",
            actionBarTitle: "选择照片",
            allViewTitle: "All Photos",
            selectCircleStrokeColor: "#000000",
          ));

      if (resultList.length > 0) {
        ctx.state.photos = resultList;
        if (ctx.state.photos != null) {
          for (int i = 0; i < ctx.state.photos.length; i++) {
            ctx.dispatch(AnswerEditActionCreator.doingOcr(i));
            var photo = ctx.state.photos[i];
            var photoData = await photo.requestOriginal(quality: 70);
            HttpResult result = await Http.uploadPhoto(
                "/publicUploadAction_upload",
                photoBuffer: photoData.buffer.asUint8List());
            if (result.success) {
              var ocr = {
                'title': result.data['articleTitle'].toString(),
                'content': result.data['articleWithoutTitle'].toString()
              };
              ctx.dispatch(AnswerEditActionCreator.doneOcr(ocr));
            } else {
              ctx.dispatch(AnswerEditActionCreator.doneOcr({}));
              Util.alertFail(result, ctx.context);
            }
          }
        }
      } else {
        Util.alert('请选择照片', ctx.context);
      }
    } catch (e) {
      print(e);
    }
  }
}

void _onVoiceAi(Action action, Context<AnswerEditState> ctx) async {
  var filePath = action.payload;

  // 结束录音, 识别
  // POST /stream/v1/asr?appkey=23****f5&format=pcm&sample_rate=16000&enable_punctuation_prediction=true&enable_inverse_text_normalization=true HTTP/1.1
  // X-NLS-Token: 450372e4279******bcc2b3c793
  var url = 'http://nls-gateway.cn-shanghai.aliyuncs.com/stream/v1/asr';
  var sampleRate = 16000;
  final _param = {
    'appkey': 'ManJi0aLPMz2C30T',
    'format': 'pcm',
    'sample_rate': sampleRate,
    'enable_punctuation_prediction': false,
    'enable_inverse_text_normalization': false,
  };

  final _headers = {
    'X-NLS-Token': ctx.state.aliToken,
    'Host': 'nls-gateway.cn-shanghai.aliyuncs.com',
  };

  var pr = new ProgressDialog(ctx.context)..setMessage('请等待...');
  pr.show();
  HttpResult result = await Http.upload(url,
      query: _param, headers: _headers, filePath: filePath);
  pr.hide();

  if (result.success) {
    print(result.data);

    var ocr = {
      'title': '',
      'content': '',
    };
    if (ctx.state.isTitle) {
      ocr['title'] = result.data;
    } else {
      ocr['content'] = result.data;
    }
    ctx.dispatch(AnswerEditActionCreator.doneOcr(ocr));
  } else {
    Util.alertFail(result, ctx.context);
  }
}

void _onAiSubmit(Action action, Context<AnswerEditState> ctx) async {
  String title = ctx.state.titleEditController.text;
  String content = ctx.state.contentEditController.text;
  var type = ctx.state.answer.articleType;
  var grade = ctx.state.answer.grade;
  var userInfo = ctx.state.userInfo;

  if (title.isEmpty) {
    Util.alert('标题不能为空', ctx.context);
    return;
  }

  if (content.length < 15) {
    Util.alert('内容不能过短', ctx.context);
    return;
  }

  // 保存
  var pr = new ProgressDialog(ctx.context)..setMessage('请等待...');
  pr.show();
  var url = '/correct/${GlobalState.userRole}/api/homework/save.mvc';
  var result = await Http.post(url, data: {
    'id': ctx.state.answer.id,
    'title': title,
    'content': content,
    'finish': '1'
  });
  pr.hide();

  if (!result.success) {
    Util.alert(result.errorMsg, ctx.context);
    return;
  }

  if (!Util.canUseAi(userInfo)) {
    bool ok =
        await Util.showConfirmDialog('会员已过期', '您的会员已过期，点击[确认]去充值', ctx.context);
    if (ok == true) {
      // 跳转去支付
      Navigator.of(ctx.context).pushNamed(Nav.PAY);
    }
    return;
  }

  // AI批改
  var done = await Navigator.of(ctx.context).pushNamed(
    Nav.WEB_PAGE,
    arguments: {
      'url':
          '/correct/pub/view/machine/review.mvc?id=${ctx.state.answer.id}&ishomework=1',
      'share': true,
      'done': '交作业',
    },
  );

  if (done != null) {
    ctx.dispatch(AnswerEditActionCreator.aiCommitted());
    ctx.dispatch(AnswerEditActionCreator.onSubmit());
  } else {
    ctx.dispatch(AnswerEditActionCreator.aiCommitted());
  }
}

void _onSubmit(Action action, Context<AnswerEditState> ctx) async {
  String title = ctx.state.titleEditController.text;
  String content = ctx.state.contentEditController.text;

  if (title.isEmpty) {
    Util.showMsgDialog('提交失败', '标题不能为空', ctx.context);
    return;
  }

  if (content.length < 15) {
    Util.showMsgDialog('提交失败', '内容不能过短', ctx.context);
    return;
  }

  if (!ctx.state.aiCommitted) {
    Util.showMsgDialog('提交失败', '请先进行AI批改', ctx.context);
    return;
  }

  var starCount = content.length - content.replaceAll("*", "").length;
  if (starCount >= 30) {
    Util.showMsgDialog(
        '提交失败', 'AI老师大约有$starCount个字符未识别，请校正后再批改，否则会影响分数哦！', ctx.context);
    return;
  }

  var url = '/correct/${GlobalState.userRole}/api/homework/save.mvc';
  HttpResult result = await Http.post(url, data: {
    'id': ctx.state.answer.id,
    'title': title,
    'content': content,
    'finish': '2'
  });

  if (result.success) {
    Util.alert('作业提交成功', ctx.context);
    Future.delayed(Duration(seconds: 1)).then((e) {
      Navigator.of(ctx.context)
          .pushNamedAndRemoveUntil(Nav.HOME, (Route<dynamic> route) => false);
    });
  }
}

void _onDemand(Action action, Context<AnswerEditState> ctx) {
  Navigator.of(ctx.context).pushNamed(Nav.DEMAND, arguments: ctx.state.answer);
}
